package com.kaikai.commonutils;

import org.springframework.beans.BeanUtils;
import org.springframework.util.ReflectionUtils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 通用Bean复制工具类，使用{@link BeanUtils}。
 */
public class BeanCopyUtils {

    /**
     * Bean复制 根据属性的get/set方法来复制
     *
     * @param srcObj
     * @param destObj
     */
    public static void copy(Object srcObj, Object destObj) {
        if (null != srcObj && null != destObj) {
            BeanUtils.copyProperties(srcObj, destObj);
        }
    }

    /**
     * Bean复制，srcObj中属性值为null的属性将不会被复制到destObj中。 根据属性的get/set方法来复制
     *
     * @param srcObj
     * @param destObj
     * @throws Exception
     */
    public static void copyIgnoreNullPropValues(Object srcObj, Object destObj) throws Exception {
        if (null != srcObj && null != destObj) {

//			Class clazz = srcObj.getClass();
//			Field[] fields = clazz.getDeclaredFields();
            Field[] fields = getAllFields(srcObj);
            List<String> ignores = new ArrayList<>();
            for (Field field : fields) {
                // 安全漏洞问题
//                field.setAccessible(true);
                ReflectionUtils.makeAccessible(field);
                String fieldName = field.getName();
                Object value = field.get(srcObj);
                if (value == null) {
                    ignores.add(fieldName);
                }
            }
            String[] a = new String[ignores.size()];
            BeanUtils.copyProperties(srcObj, destObj, ignores.toArray(a));
        }
    }

    /**
     * 批量复制，将srcList中的每个JavaBean的属性复制到destList对象中，destList中会自动新建对应的实例并复制属性
     *
     * @param srcList
     * @param destList
     * @param destClazz
     */
    public static void copyList(List srcList, List destList, Class<?> destClazz) {
        if (null != srcList && !srcList.isEmpty() && null != destList) {
            try {
                Object deskObj = null;
                for (Object obj : srcList) {
                    deskObj = destClazz.newInstance();
                    BeanUtils.copyProperties(obj, deskObj);
                    destList.add(deskObj);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 深拷贝数组
     *
     * @param <T>
     * @param src
     * @return
     */
    public static <T> List<T> deepCopy(List<T> src) {
        if (src == null) {
            return null;
        }
        if (src.size() == 0) {
            return new ArrayList<T>();
        }
        try {
            ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(byteOut);
            out.writeObject(src);

            ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
            ObjectInputStream in = new ObjectInputStream(byteIn);
            List<T> dest = (List<T>) in.readObject();
            return dest;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("深拷贝数组失败.", e);
        }

    }

    public static Field[] getAllFields(Object object) {
        Class clazz = object.getClass();
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null) {
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        return fields;
    }
}